package cn.hongxin.sap.conn.aspect;

import cn.getech.poros.framework.common.api.RestResponse;
import cn.hongxin.basic.business.client.BasicSystemDictClient;
import cn.hongxin.basic.business.dto.SysTableDto;
import cn.hongxin.basic.business.response.DictItemResp;
import cn.hongxin.busi.common.annotation.Dict;
import cn.hongxin.busi.common.constant.CommonConstant;
import cn.hongxin.busi.common.util.oConvertUtils;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Description: 字典aop类
 * @Author: dangzhenghui
 * @Date: 2019-3-17 21:50
 * @Version: 1.0
 */
@Aspect
@Component
@Slf4j
public class DictAspect {

    @Autowired
    private BasicSystemDictClient basicSystemDictClient;


    // 定义切点Pointcut
    @Pointcut("execution(public * cn.hongxin.sap.conn..*.*Controller.*(..))")
    public void excudeService() {
    }

    @Around("excudeService()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        long time1 = System.currentTimeMillis();
        Object result = pjp.proceed();
        long time2 = System.currentTimeMillis();
        log.debug("获取JSON数据 耗时：" + (time2 - time1) + "ms");
        long start = System.currentTimeMillis();
        this.parseDictText(result);
        long end = System.currentTimeMillis();
        log.debug("解析注入JSON数据  耗时" + (end - start) + "ms");
        return result;
    }

    /**
     * 本方法针对返回对象为Result 的IPage的分页列表数据进行动态字典注入
     * 字典注入实现 通过对实体类添加注解@dict 来标识需要的字典内容,字典分为单字典code即可 ，table字典 code table text配合使用与原来jeecg的用法相同
     * 示例为SysUser   字段为sex 添加了注解@Dict(dicCode = "sex") 会在字典服务立马查出来对应的text 然后在请求list的时候将这个字典text，已字段名称加_dictText形式返回到前端
     * 例输入当前返回值的就会多出一个sex_dictText字段
     * {
     * sex:1,
     * sex_dictText:"男"
     * }
     * 前端直接取值sext_dictText在table里面无需再进行前端的字典转换了
     * customRender:function (text) {
     * if(text==1){
     * return "男";
     * }else if(text==2){
     * return "女";
     * }else{
     * return text;
     * }
     * }
     *
     * @param result
     */
    private void parseDictText(Object result) {
        if (result instanceof RestResponse) {
            if (((RestResponse) result).getData() instanceof IPage) {
                List<JSONObject> items = new ArrayList<>();

                Map<String, String> dictMap = new HashMap<>();
                for (Object record : ((IPage) ((RestResponse) result).getData()).getRecords()) {
                    ObjectMapper mapper = new ObjectMapper();
                    String json = "{}";
                    try {
                        json = mapper.writeValueAsString(record);
                    } catch (JsonProcessingException e) {
                        log.error("json解析失败" + e.getMessage(), e);
                    }
                    JSONObject item = JSONObject.parseObject(json);
                    for (Field field : oConvertUtils.getAllFields(record)) {
                        if (field.getAnnotation(Dict.class) != null) {
                            String code = field.getAnnotation(Dict.class).dicCode();
                            String text = field.getAnnotation(Dict.class).dicText();
                            String table = field.getAnnotation(Dict.class).dictTable();
                            String key = String.valueOf(item.get(field.getName()));

                            String textValue = "";
                            //翻译字典值对应的txt
                            if (StringUtils.isBlank(table)) {
                                dictMap = getDictMap(code);
                                String tmpValue;
                                StringBuilder valueBuilder = new StringBuilder();
                                String[] keys = key.split(",");
                                for (String k : keys) {
                                    if (k.trim().length() == 0) {
                                        continue; //跳过循环
                                    }
                                    tmpValue = dictMap.get(key);
                                    valueBuilder.append(tmpValue);
                                }
                                textValue = valueBuilder.toString();
                            } else {
                                textValue = translateDictValue(code, text, table, key);
                            }

                            log.debug(" 字典Val : " + textValue);
                            log.debug(" __翻译字典字段__ " + field.getName() + CommonConstant.DICT_TEXT_SUFFIX + "： " + textValue);
                            item.put(field.getName() + CommonConstant.DICT_TEXT_SUFFIX, textValue);
                        }
                        //date类型默认转换string格式化日期
                        if (field.getType().getName().equals("java.util.Date") && field.getAnnotation(JsonFormat.class) == null && item.get(field.getName()) != null) {
                            SimpleDateFormat aDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                            item.put(field.getName(), aDate.format(new Date((Long) item.get(field.getName()))));
                        }
                    }
                    items.add(item);
                }
                ((IPage) ((RestResponse) result).getData()).setRecords(items);
                dictCodeMap.clear();
            }

        }

    }


    private static Map<String, Map<String, String>> dictCodeMap = new HashMap<>();


    private Map<String, String> getDictMap(String code) {
        List<DictItemResp> dictItemRespList;
        Map<String, String> dictMap = new HashMap<>();

        if (dictCodeMap.get(code) != null && dictCodeMap.get(code).size() > 0) {
            return dictCodeMap.get(code);
        }

        try {
            RestResponse<List<DictItemResp>> restResponse = basicSystemDictClient.queryDictItemByCodeAndValue(code, null);
            log.info("调用[busi-system-service]服务[queryDictItemByCodeAndValue]方法-入参：{}-返回值：{}", code, JSONObject.toJSONString(restResponse));
            if (restResponse.isSuccess()) {
                dictItemRespList = restResponse.getData();
                for (DictItemResp dictItemResp : dictItemRespList) {
                    dictMap.put(dictItemResp.getItemValue(), dictItemResp.getItemText());
                }
                dictCodeMap.put(code, dictMap);
            }
        } catch (Exception e) {
            log.error("[失败调用[busi-system-service]服务[queryDictItemByCodeAndValue]方法", e);
        }
        return dictMap;
    }


    /**
     * 翻译字典文本
     *
     * @param code
     * @param text
     * @param table
     * @param key
     * @return
     */
    private String translateDictValue(String code, String text, String table, String key) {
        if (StringUtils.isEmpty(key)) {
            return null;
        }
        StringBuilder textValue = new StringBuilder();
        String[] keys = key.split(",");


        for (String k : keys) {
            String tmpValue = null;
            log.debug(" 字典 key : " + k);
            if (k.trim().length() == 0) {
                continue; //跳过循环
            }
            if (!StringUtils.isEmpty(table)) {
                try {
                    SysTableDto sysTableDto = new SysTableDto();
                    sysTableDto.setTable(table);
                    sysTableDto.setText(text);
                    sysTableDto.setCode(code);
                    sysTableDto.setKey(k.trim());

                    RestResponse restResponse = basicSystemDictClient.queryTableDictTextByKey(sysTableDto);
                    if (restResponse.isSuccess()) {
                        tmpValue = (String) restResponse.getData();
                    }
                } catch (Exception e) {
                    log.error("失败调用[busi-system-service]服务[queryTableDictTextByKey]方法", e);
                }
            }
            if (tmpValue != null) {
                if (!"".equals(textValue.toString())) {
                    textValue.append(",");
                }
                textValue.append(tmpValue);
            }
        }
        return textValue.toString();
    }

}
